package com.example.myapplication.algorithm;

import java.util.ArrayList;
import java.util.List;

public class algorithm {
    private static algorithm INSTANCE;
    public synchronized static algorithm getInstance() {
        if (INSTANCE == null) {
            INSTANCE = new algorithm();
        }
        return INSTANCE;
    }
    public final int FR = 256;
    public double[] ecgData = new double[FR * 2];
    public int index = 0;
    /**
     * 从ECG数据中计算心率
     *
     * @param ecgData ECG数据数组（采样率256Hz）
     * @param windowSize 分析窗口大小（秒），建议5-10秒
     * @return 心率值（次/分钟），如果没有足够数据则返回-1
     */
    public double calculateHeartRate(double[] ecgData, int windowSize) {
        // 参数校验
        if (ecgData == null || ecgData.length == 0 || windowSize <= 0) {
            return -1;
        }

        // 计算窗口内的样本数
        int windowSamples = windowSize * FR;
        if (ecgData.length < windowSamples) {
            // 如果数据不足，使用所有可用数据
            windowSamples = ecgData.length;
        }

        // 寻找R波峰值
        List<Integer> rPeakIndices = findRPeaks(ecgData, windowSamples);
        //Log.d("lzy", "rPeakIndices波峰值数量: " + rPeakIndices.size());

        // 计算平均心率
        if (rPeakIndices.size() < 2) {
            return -1; // 无法计算心率
        }

        // 计算RR间期（毫秒）
        double totalRRInterval = 0;
        for (int i = 1; i < rPeakIndices.size(); i++) {
            int rrInterval = rPeakIndices.get(i) - rPeakIndices.get(i - 1);
            totalRRInterval += rrInterval;
        }
        double avgRRInterval = totalRRInterval / (rPeakIndices.size() - 1);

        // 转换为心率（次/分钟）
        double heartRate = (60.0 * FR) / avgRRInterval;

        return heartRate;
    }

    /**
     * 在ECG数据中检测R波峰值
     *
     * @param ecgData ECG数据数组
     * @param length 要分析的数据长度
     * @return R波峰值的索引列表
     */
    private  List<Integer> findRPeaks(double[] ecgData, int length) {
        List<Integer> rPeakIndices = new ArrayList<>();

        // 参数设置（可根据实际ECG数据调整）
        double threshold = 0.6 * getMaxValue(ecgData, length); // 初始阈值
        int refractoryPeriod = 100; // 不应期（样本数），约0.4秒

        int lastPeakIndex = -refractoryPeriod;

        // 寻找超过阈值的峰值
        for (int i = 1; i < length - 1; i++) {
            // 简单的峰值检测
            if (ecgData[i] > ecgData[i - 1] && ecgData[i] > ecgData[i + 1] && ecgData[i] > threshold) {
                // 检查不应期
                if (i - lastPeakIndex > refractoryPeriod) {
                    rPeakIndices.add(i);
                    lastPeakIndex = i;

                    // 动态调整阈值
                    threshold = 0.4 * threshold + 0.6 * ecgData[i];
                }
            }
        }

        return rPeakIndices;
    }

    /**
     * 获取数组中的最大值
     */
    private double getMaxValue(double[] array, int length) {
        double max = Double.MIN_VALUE;
        for (int i = 0; i < length; i++) {
            if (array[i] > max) {
                max = array[i];
            }
        }
        return max;
    }
}
